package com.hawk.eye.server.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hawk.eye.api.storage.dto.LogMessageDTO;
import com.hawk.eye.framework.config.properties.HawkEyeServerProperties;
import com.hawk.eye.framework.utils.CollectionUtil;
import com.hawk.eye.framework.utils.ExceptionUtils;
import com.hawk.eye.framework.core.domain.entity.SysUser;
import com.hawk.eye.common.page.PageQuery;
import com.hawk.eye.common.page.PageResult;
import com.hawk.eye.framework.utils.ObjectUtil;
import com.hawk.eye.framework.utils.SecurityUtils;
import com.hawk.eye.server.constant.WorkOrderStatusEnum;
import com.hawk.eye.server.convert.RepairWorkOrderConvert;
import com.hawk.eye.server.delegate.LogMessageStorageDelegate;
import com.hawk.eye.server.domain.dto.req.RepairApiReqDTO;
import com.hawk.eye.server.domain.dto.req.RepairWorkOrderReqDTO;
import com.hawk.eye.server.domain.dto.resp.RepairApiRespDTO;
import com.hawk.eye.server.domain.dto.resp.RepairWorkOrderRespDTO;
import com.hawk.eye.api.storage.dto.ServiceLogRespDTO;
import com.hawk.eye.server.domain.po.RepairWorkOrder;
import com.hawk.eye.server.mapper.RepairWorkOrderMapper;
import com.hawk.eye.server.service.IRepairApiService;
import com.hawk.eye.server.service.IRepairWorkOrderService;
import com.hawk.eye.server.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service业务层处理
 *
 * @author salad
 * @date 2023-09-23
 */
@Service
@RequiredArgsConstructor
public class RepairWorkOrderServiceImpl extends ServiceImpl<RepairWorkOrderMapper, RepairWorkOrder> implements IRepairWorkOrderService {

    private final RepairWorkOrderMapper repairWorkOrderMapper;

    private final ISysUserService userService;

    private final IRepairApiService repairApiService;

    private final LogMessageStorageDelegate logStorageDelegate;

    private final HawkEyeServerProperties properties;

    @Override
    public void createRepairWorkOrderIfMatched(LogMessageDTO dataDTO) {
        //对异常进行近似度匹配，创建修复工单
        if (properties.getEnabledRepairWorkOrder()) {
            String stackHash = dataDTO.getStackHash();
            Long nodeUser = 0L;
            if (ObjectUtil.isNotEmpty(dataDTO.getChargeUserId())) {
                nodeUser = dataDTO.getChargeUserId();
            }
            RepairApiRespDTO repairApi = repairApiService.getRepairApiByStackHash(stackHash);
            if (repairApi != null) {
                RepairWorkOrder rwo = new RepairWorkOrder();
                rwo.setBaseAlarmId(dataDTO.getBaseAlarmId());
                rwo.setRepairApiId(repairApi.getId());
                rwo.setStatus(WorkOrderStatusEnum.WAIT_REVIEW.getValue());
                rwo.setTraceId(dataDTO.getTraceId());
                rwo.setStackHash(stackHash);
                rwo.setWorkOrderName("使用[" + repairApi.getName() + "]修复[" + stackHash + "]异常");
                rwo.setRecordTime(LocalDateTime.now());
                rwo.setNodeUser(nodeUser);
                repairWorkOrderMapper.insert(rwo);
            }
        }
    }

    @Override
    public PageResult<RepairWorkOrderRespDTO> page(PageQuery pageQuery, RepairWorkOrderReqDTO reqDTO) {
        reqDTO.setNodeUser(SecurityUtils.getUserId());
        IPage<RepairWorkOrderRespDTO> page = repairWorkOrderMapper.page(pageQuery.toPage(), reqDTO);
        List<Long> userIds = page.getRecords()
                .stream().map(RepairWorkOrderRespDTO::getNodeUser)
                .filter(e -> e != 0).distinct().collect(Collectors.toList());
        Map<Long, String> userAsMap = new HashMap<>(16);
        if (CollectionUtil.isNotEmpty(userIds)) {
            List<SysUser> sysUsers = userService.selectUserByIds(userIds);
            userAsMap = sysUsers
                    .stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getNickName));
        }
        for (RepairWorkOrderRespDTO record : page.getRecords()) {
            if (record.getNodeUser() == 0) {
                record.setNodeUserName("所有人可见");
            } else {
                record.setNodeUserName(userAsMap.get(record.getNodeUser()));
            }
            record.setStatusText(WorkOrderStatusEnum.getName(record.getStatus()));
        }
        return PageResult.of(page);
    }


    @Override
    public RepairWorkOrderRespDTO detail(Long id) {
        ExceptionUtils.isEmptyThrow(id, "参数[id]不能为空");
        RepairWorkOrder repairWorkOrder = baseMapper.detail(id);
        ExceptionUtils.isEmptyThrow(repairWorkOrder, "该工单已经不存在,请刷新界面");
        RepairWorkOrderRespDTO respDTO = RepairWorkOrderConvert.INSTANCE.to(repairWorkOrder);
        Long nodeUser = respDTO.getNodeUser();
        if (nodeUser == null || nodeUser == 0) {
            respDTO.setNodeUserName("所有人可见");
        } else {
            SysUser user = userService.selectUserById(nodeUser);
            respDTO.setNodeUserName(user == null ? "该审核人员已被删除" : user.getNickName());
        }
        Long repairApiId = respDTO.getRepairApiId();
        RepairApiRespDTO repairApiRespDTO = repairApiService.detail(repairApiId);
        Long baseAlarmId = repairWorkOrder.getBaseAlarmId();
        ServiceLogRespDTO detail = logStorageDelegate.getAlarmLogStorage().detail(baseAlarmId);
        return RepairWorkOrderConvert.INSTANCE.to(repairWorkOrder, repairApiRespDTO, detail);
    }

    @Override
    public Boolean approve(RepairWorkOrderReqDTO reqDTO) {
        Long id = reqDTO.getId();
        ExceptionUtils.isEmptyThrow(id, "参数[id]不能为空");
        RepairWorkOrder repairWorkOrder = getById(id);
        ExceptionUtils.isEmptyThrow(repairWorkOrder, "该工单已经不存在,请刷新界面");
        repairWorkOrder.setStatus(WorkOrderStatusEnum.REVIEWED_WAIT_EXEC.getValue());
        return updateById(repairWorkOrder);
    }

    @Override
    public Boolean reject(RepairWorkOrderReqDTO reqDTO) {
        Long id = reqDTO.getId();
        ExceptionUtils.isEmptyThrow(id, "参数[id]不能为空");
        RepairWorkOrder repairWorkOrder = getById(id);
        ExceptionUtils.isEmptyThrow(repairWorkOrder, "该工单已经不存在,请刷新界面");
        repairWorkOrder.setStatus(WorkOrderStatusEnum.REJECT.getValue());
        return updateById(repairWorkOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean executeRepairApi(RepairWorkOrderReqDTO reqDTO) {
        ExceptionUtils.isEmptyThrow(reqDTO.getId(), "参数[id]不能为空");
        ExceptionUtils.isEmptyThrow(reqDTO.getRepairApiId(), "参数[repairApiId]不能为空");
        RepairApiReqDTO repairApiReqDTO = new RepairApiReqDTO();
        repairApiReqDTO.setId(reqDTO.getRepairApiId());
        repairApiReqDTO.setParamsAsString(reqDTO.getParamsAsString());
        repairApiReqDTO.setHeadersAsString(reqDTO.getHeadersAsString());
        repairApiReqDTO.setBodyAsString(reqDTO.getBodyAsString());
        Boolean success = repairApiService.executeRepairApi(repairApiReqDTO);
        update(Wrappers.<RepairWorkOrder>lambdaUpdate()
                .set(RepairWorkOrder::getStatus, WorkOrderStatusEnum.REVIEWED_EXECED.getValue())
                .eq(RepairWorkOrder::getId, reqDTO.getId()));
        return success;
    }

}
